﻿using LowCoding.Common.Security;
using LowCoding.Common;
using LowCoding.Domain.Entity;
using LowCoding.Dto.Sys;
using LowCoding.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LowCoding.Application
{
    public class MenuPermission : ServiceBase<SysRight, SysRightInput, SysRightOutput, SysRightSearchInput, string>
    {
        /// <summary>
        /// 根据用户id查询用户权限
        /// </summary>
        /// <returns></returns>
        public async Task<List<TreeMainDto>> GetRoleRightsMod(string userId)
        {
            //三表联查,角色模块表、用户角色表、模块(权限表)
            //通过角色模块表中的角色Id和用户角色表的角色Id进行关联
            //角色模块表中的模块Id和模块(权限表的主Id)进行关联
            //加入查询条件角色模块表中的用户Id 是否等于传过来的用户Id and
            //用户角色表的是否有效and是否删除(获取枚举1or0)接着查重
            //再select查询三个表 new到APPModuleDto 里面去再进行显示
            var data = await _client.Queryable<SysRight>()
                .InnerJoin<SysUserrole>((t, t1) => t.RgtRoleId == t1.RleId)
                .InnerJoin<SysModule>((t, t1, t2) => t.RgtMdlId == t2.Id)
                .Where((t, t1, t2) => t1.UerId == userId && t2.MdlValid == "Y" &&
                t2.Isdel == IsDel.No.GetEnumValue())
                .Distinct()
                .Select((t, t1, t2) => new AppModuleDto()
                {
                    Id = t2.Id,
                    ModuleCode = t2.MdlCode,
                    ModuleName = t2.MdlName,
                    ParentModuleCode = t2.MdlParent,
                    IconCls = t2.MdlIconcls,
                    ModuleSeq = t2.MdlSeq,
                    ModuleUrl = t2.MdlUrl,
                    ModuleType = t2.MdlType
                }).ToListAsync();
            //实例化菜单Dto
            var mdlViews = new List<TreeMainDto>();
            //用上面三表联查查出来的数据加查询条件
            var firstModules = data.Where(c => c.ParentModuleCode == AppModuleDto.RootModuleCode)
                .OrderBy(c => c.ModuleSeq).ToList();

            foreach (var mdl in firstModules)
            {
                mdlViews.Add(new TreeMainDto()
                {
                    Id = mdl.Id,
                    MdlCode = mdl.ModuleCode,
                    MdlName = mdl.ModuleName,
                    IconCls = mdl.IconCls,
                    ModuleUrl = mdl.ModuleUrl ?? "/" + mdl.ModuleCode,
                    children = GetChildrenMdl(data, mdl.ModuleCode),
                    Functions = new List<TreeMainDto>()
                });
            }
            return mdlViews;
        }

        private List<TreeMainDto> GetChildrenMdl(List<AppModuleDto> allMdl, string mdlCode)
        {
            var childModule = allMdl.FindAll(c => c.ParentModuleCode == mdlCode && c.ModuleType == "M");
            var list = childModule.OrderBy(s => s.ModuleSeq).ToList();
            var dptView = new List<TreeMainDto>();
            foreach (var mdl in list)
            {
                dptView.Add(new TreeMainDto()
                {
                    Id = mdl.Id,
                    MdlCode = mdl.ModuleCode,
                    MdlName = mdl.ModuleName,
                    IconCls = mdl.IconCls,
                    ModuleUrl = mdl.ModuleUrl,
                    children = GetChildrenMdl(allMdl, mdl.ModuleCode),
                    Functions = GetFunctionsMdl(allMdl, mdl.ModuleCode)
                }); ;
            }
            return dptView;
        }

        private List<TreeMainDto> GetFunctionsMdl(List<AppModuleDto> allMdl, string mdlCode)
        {
            var childModule = allMdl.FindAll(c => c.ParentModuleCode == mdlCode && c.ModuleType == "F").OrderBy(c => c.ModuleSeq);
            var dptView = new List<TreeMainDto>();
            foreach (var mdl in childModule)
            {
                dptView.Add(new TreeMainDto()
                {
                    Id = mdl.Id,
                    MdlCode = mdl.ModuleCode,
                    MdlName = mdl.ModuleName,
                    IconCls = mdl.IconCls,
                    ModuleUrl = mdl.ModuleUrl
                });
            }
            return dptView;
        }

        /// <summary>
        /// 根据roleId查询所有的菜单信息并标注权限是否拥有
        /// </summary>
        /// <param name="roleid"></param>
        /// <returns></returns>
        public async Task<List<TreeSysRightDto>> GetSysRoleRights(string roleid, string mdlCode = "")
        {
            List<string> ids = new List<string>();
            if (!string.IsNullOrEmpty(mdlCode))
            {
                ids = await GetIds(mdlCode);
            }

            List<SysModule> allModuless = await _client.Queryable<SysModule>()
                .Where(it => it.Isdel == IsDel.No.GetEnumValue())
                .WhereIF(!string.IsNullOrEmpty(mdlCode), it => ids.Contains(it.Id))
                .ToListAsync();
            List<SysRight> roleRightses = await _client.Queryable<SysRight>()
                .Where(it => it.RgtRoleId == roleid).ToListAsync();
            var mdlViews = new List<TreeSysRightDto>();
            var firstModules = allModuless
                .Where(c => c.MdlParent == AppModuleDto.RootModuleCode)
                .OrderBy(c => c.MdlSeq).ToList();
            foreach (var mdl in firstModules)
            {
                mdlViews.Add(new TreeSysRightDto()
                {
                    id = mdl.Id,
                    MdlName = mdl.MdlName,
                    children = GetChildrenMdl(allModuless, mdl.MdlCode, roleRightses),
                    HasRights = roleRightses.Find(c => c.RgtMdlId == mdl.Id) != null,
                    Functions = new List<TreeSysRightDto>()
                });
            }
            return mdlViews;
        }

        /// <summary>
        /// 根据模块代码模块id集合
        /// </summary>
        /// <param name="mdlCode"></param>
        /// <returns></returns>
        public async Task<List<string>> GetIds(string mdlCode)
        {
            //id集合
            List<string> ids = new List<string>();

            //一级-平台
            var dataFirst = await _client.Queryable<SysModule>().Select(it => new SysModule { Id = it.Id, MdlCode = it.MdlCode }).FirstAsync(it => it.MdlCode == mdlCode);
            if (dataFirst != null)
            {
                ids.Add(dataFirst.Id);
                //二级-导航栏
                var dataSecond = await _client.Queryable<SysModule>().Where(it => it.MdlParent == dataFirst.MdlCode)
                    .Select(it => new SysModule { Id = it.Id, MdlCode = it.MdlCode }).ToListAsync();
                foreach (var sItem in dataSecond)
                {
                    ids.Add(sItem.Id);
                    //三级-导航
                    List<SysModule> dataThird = await _client.Queryable<SysModule>().Where(it => it.MdlParent == sItem.MdlCode)
                        .Select(it => new SysModule { Id = it.Id, MdlCode = it.MdlCode }).ToListAsync();
                    foreach (var tItem in dataThird)
                    {
                        ids.Add(tItem.Id);
                        //四级-按钮
                        var dataFourth = await _client.Queryable<SysModule>().Where(it => it.MdlParent == tItem.MdlCode)
                            .Select(it => it.Id).ToListAsync();
                        foreach (var fItem in dataFourth)
                        {
                            ids.Add(fItem);
                        }
                    }
                }
            }
            return ids;
        }

        private List<TreeSysRightDto> GetChildrenMdl(List<SysModule> allMdl, string mdlCode, List<SysRight> roleRightses)
        {
            var childModule = allMdl.FindAll(c => c.MdlParent == mdlCode && c.MdlType == "M").OrderBy(c => c.MdlSeq);
            var dptView = new List<TreeSysRightDto>();
            foreach (var mdl in childModule)
            {
                dptView.Add(new TreeSysRightDto()
                {
                    id = mdl.Id,
                    MdlName = mdl.MdlName,
                    children = GetChildrenMdl(allMdl, mdl.MdlCode, roleRightses),
                    Functions = GetFunctionsMdl(allMdl, mdl.MdlCode, roleRightses),
                    HasRights = roleRightses.Find(c => c.RgtMdlId == mdl.Id) != null
                }); ;
            }
            return dptView;
        }

        private List<TreeSysRightDto> GetFunctionsMdl(List<SysModule> allMdl, string mdlCode, List<SysRight> roleRightses)
        {
            var childModule = allMdl.FindAll(c => c.MdlParent == mdlCode && c.MdlType == "F").OrderBy(c => c.MdlSeq);
            var dptView = new List<TreeSysRightDto>();
            foreach (var mdl in childModule)
            {
                dptView.Add(new TreeSysRightDto()
                {
                    id = mdl.Id,
                    MdlName = mdl.MdlName,
                    HasRights = roleRightses.Find(c => c.RgtMdlId == mdl.Id) != null
                }); ;
            }
            return dptView;
        }

        /// <summary>
        /// 更新角色权限(可更新特定平台)
        /// </summary>
        /// <param name="roleid"></param>
        /// <param name="rights"></param>
        /// <returns></returns>
        public async Task<ResponseMessageModel> SysRightUpdate(string roleid, List<string> rights, string mdlCode = "")
        {
            if (!await IsAdminAsync())
            {
                return ToJsonTran.Fail("所在角色禁止修改权限！");
            }

            if (!await _client.Queryable<SysRole>().Where(it => it.Id == roleid && it.Isdel == IsDel.No.GetEnumValue()).AnyAsync())
            {
                return ToJsonTran.Fail("角色不存在");
            }

            List<string> ids = new List<string>();
            if (!string.IsNullOrEmpty(mdlCode))
            {
                ids = await GetIds(mdlCode);
                await _client.Deleteable<SysRight>()
                   .Where(it => it.RgtRoleId == roleid && ids.Contains(it.RgtMdlId))
                   .ExecuteCommandAsync();
            }
            else
            {
                await _client.Deleteable<SysRight>()
                 .Where(it => it.RgtRoleId == roleid)
                 .ExecuteCommandAsync();
            }
            var data = rights.Select(it => new SysRight() { Id = Ids.NextIdString(), RgtRoleId = roleid, RgtMdlId = it }).ToList();
            if (data.Count > 0)
            {
                await _client.Insertable<SysRight>(data).ExecuteCommandAsync();
            }
            return ToJsonTran.Success();
        }



        /// <summary>
        /// 判断当前登录用户是否管理员
        /// </summary>
        /// <returns></returns>
        public async Task<bool> IsAdminAsync()
        {
            try
            {
                //获取当前登录用户
                var user = AppManager.GetCurrentUser();

                var data = await _client.Queryable<SysUserrole>()
                    .LeftJoin<SysRole>((su, sy) => su.RleId == sy.Id)
                    .Where((su, sy) => su.UerId == user.UserId && sy.RleIsp == "1")
                    .CountAsync();

                if (data > 0)
                {
                    return true;
                }

                return false;
            }
            catch (System.Exception e)
            {
                return false;
            }
        }

    }
}
